#include "../include/scNet/SocketWrapper.hpp"
#include <fcntl.h>
#include <string>
#include <system_error>

namespace scNet {

	
	// 构造 创建套接字
	/**
     * @brief 构造函数，创建套接字
     * @param domain 套接字域，通常使用 AF_INET（IPv4）或 AF_INET6（IPv6）
     * @param type 套接字类型，通常使用 SOCK_STREAM（TCP）或 SOCK_DGRAM（UDP）
     * @param protocol 协议类型，默认为0，表示使用默认协议
     * 
     * 创建一个套接字，失败抛运行时异常。
     */
	SocketWrapper::SocketWrapper(int domain, int type, int protocol) {
		sockfd_ = socket(domain, type, protocol);
		if (sockfd_ < 0)		
			throw std::system_error(errno, std::generic_category(), "Socket creation failed");
	}

	SocketWrapper::SocketWrapper(int sockfd) : sockfd_(sockfd) {
	    if (sockfd_ < 0) {
	        throw std::runtime_error("Invalid socket file descriptor");
	    }
	}

	/**
     * @brief 析构函数，关闭套接字
     * 如果套接字有效，关闭套接字，释放资源。
     */
	SocketWrapper::~SocketWrapper() {
		// 多线程使用
		std::lock_guard<std::mutex> lock(mutex_);
		if (sockfd_ != -1) {
			close(sockfd_);
			sockfd_ = -1;
		} 		
	}

	// 移动构造
	// 构造可以使用初始化列表
	SocketWrapper::SocketWrapper(SocketWrapper&& other) noexcept  : sockfd_(other.sockfd_) {
    	other.sockfd_ = -1;
	}

	// 移动赋值
	SocketWrapper& SocketWrapper::operator=(SocketWrapper&& other) noexcept {
		if (this != &other) {
			// 本实例和其他不一样 上锁管理
			std::lock_guard<std::mutex> lock(mutex_);
			if (sockfd_ != -1) {
				// 文件描述符有效就要关闭了
				close(sockfd_);
			}
			this->sockfd_ = other.sockfd_;
			// 移动的也给-1 表示失效
			other.sockfd_ = -1;
		}// 返回自身指针
		return *this;
	}

	/**
	 * @brief 绑定套接字到地址
	 * @param addr 地址结构 指定要绑定的地址
	 * @param addrlen 地址结构长度
	 * 套接字绑定到指定地址 失败抛running time 异常
	 */
	void SocketWrapper::bind(const struct sockaddr* addr, socklen_t addrlen) {
		// 每一步都上锁
		std::lock_guard<std::mutex> lock(mutex_);
		// 系统函数绑定套接字
		if (::bind(sockfd_, addr, addrlen) < 0)		
			throw std::system_error(errno, std::generic_category(), "Bind failed");
	}
	/**
	 * @brief 监听套接字
	 * @param backloglen 等待队列的最大长度
	 */
	void SocketWrapper::listen(int backloglen) {
		// 每一步都上锁
		std::lock_guard<std::mutex> lock(mutex_);
		if (::listen(sockfd_, backloglen) < 0)		
			throw std::system_error(errno, std::generic_category(), "Listen failed");
	}
	/**
	 * @brief 接受连接
	 * @param addr 客户端地址结构
     * @param addrlen 地址结构的长度
     * @return 客户端连接的套接字文件描述符
	 * 接受客户端的连接请求，返回与客户端连接的套接字文件描述符。接受连接失败，抛出异常
	 */
	int SocketWrapper::accept(struct sockaddr* addr, socklen_t* addrlen) {
		// 每一步都上锁
		std::lock_guard<std::mutex> lock(mutex_);
		int client_fd = ::accept(sockfd_, addr, addrlen);
		if (client_fd < 0) {
			throw std::system_error(errno, std::generic_category(), "Accpet failed");
		}
		return client_fd; 
	}
	/**
	 * @brief 连接到指定服务器
	 * @param addr 服务器的地址结构
	 * @param addrlen 地址结构的长度
	 * 客户端连接到指定的服务器。失败抛运行时异常
	 */
	void SocketWrapper::connect(const struct sockaddr* addr, socklen_t addrlen) {
		// 每一步都上锁
		std::lock_guard<std::mutex> lock(mutex_);
		if (::connect(sockfd_, addr, addrlen) < 0) {
			throw std::system_error(errno, std::generic_category(), "Connection failed");
		}
	}
	/**
     * @brief 发送数据
     * @param buf 要发送的数据缓冲区
     * @param len 数据长度
     * @param flags 发送标志，默认为0
     * @return 发送的字节数
     * 
     * 通过套接字发送数据。发送失败返回负值。
     */
    ssize_t SocketWrapper::send(const void* buf, size_t len, int flags) {
		std::lock_guard<std::mutex> lock(mutex_);
        ssize_t ans = ::send(sockfd_, buf, len, flags); // 调用系统函数发送数据
		if (ans < 0) {
			throw std::system_error(errno, std::generic_category(), "Send failed");
		}
		return ans;
    }

    /**
     * @brief 接收数据
     * @param buf 数据接收缓冲区
     * @param len 缓冲区大小
     * @param flags 接收标志，默认为0
     * @return 接收到的字节数
     * 
     * 通过套接字接收数据接收失败返回负值。
     */
    ssize_t SocketWrapper::recv(void* buf, size_t len, int flags) {
		std::lock_guard<std::mutex> lock(mutex_);
        ssize_t ans = ::recv(sockfd_, buf, len, flags); // 调用系统函数接收数据
		if (ans < 0) {
			throw std::system_error(errno, std::generic_category(), "Receive failed");
		}
		return ans;
    }

    /**
     * @brief 获取套接字文件描述符
     * @return 套接字文件描述符
     * 
     * 返回当前套接字的文件描述符。
     */
    int SocketWrapper::getFd() const { 
		std::lock_guard<std::mutex> lock(mutex_); 
		return sockfd_; 
	}

	// 设置套接字为非阻塞模式或阻塞模式
	// 设置非阻塞
	void SocketWrapper::setNonBlocking(bool nonBlocking) {
		std::lock_guard<std::mutex> lock(mutex_);
		int flag = fcntl(sockfd_, F_GETFL, 0);
		if (flag == -1)
			throw std::system_error(errno, std::generic_category(), "fcntl(F_GETFL) failed");

		// 根据nonBlocking的值设置O_NONBLOCK标志
		if (nonBlocking) 	flag |= O_NONBLOCK;			// 设置非阻塞模式
		else				flag &= ~O_NONBLOCK;		// 设置阻塞模式

		// 设置新的文件状态标志     
		if (fcntl(sockfd_, F_SETFL, flag) == -1)
			throw std::system_error(errno, std::generic_category(), "fcntl(F_SETFL) failed");
	}

	// 设置套接字的发送和接收超时时间
	// 超时单位为毫秒
	void SocketWrapper::setTimeout(int timeoutsMs) {
		std::lock_guard<std::mutex> lock(mutex_);
		struct timeval tv;
		tv.tv_sec = timeoutsMs / 1000;
		tv.tv_usec = (timeoutsMs % 1000) * 1000;
		// 设置接收超时
		if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
			throw std::system_error(errno, std::generic_category(), "Set receive timeouts failed");
		// 设置发送超时
		if (setsockopt(sockfd_, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
			throw std::system_error(errno, std::generic_category(), "Set send timeout failed");
	}
	
}

